package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.tbit.main.constant.*;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.service.core.impl.UserInfoServiceImpl;
import com.tbit.main.util.DateTimeUtil;
import com.tbit.main.util.GeoUtil;
import com.tbit.main.util.LogUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service("rideLogListenter")
public class RideLogListenter {

    @Autowired
    private DataService dataService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MachineNoIncomeService machineNoIncomeService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private WorkOrderQuartzService workOrderQuartzService;
    @Autowired
    private WorkOrderFinishingService workOrderFinishingService;
    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private PowerChangeLogService powerChangeLogService;
    @Autowired
    private DispatchLogService dispatchLogService;
    @Autowired
    private PowerChangePerformanceService powerChangePerformanceService;
    @Autowired
    private DispatchPerformanceService dispatchPerformanceService;
    @Autowired
    private MovePerformanceService movePerformanceService;
    @Autowired
    private UserInfoServiceImpl userInfoService;
    @Autowired
    private MoveLogService moveLogService;

    @RabbitListener(queues = {"${mq.queue.tbitUqbikeRidePush}"}, concurrency = "5")
    @RabbitHandler
    public void onMessage(Message msg) {
        try {
            String respMsg = new String(msg.getBody(), StandardCharsets.UTF_8);
            /**判断消息类型*/
            JSONObject object = JSON.parseObject(respMsg);
            int msgId = object.getIntValue("msgId");

            if (msgId == GatewayProtocol.MQ_MSG_ID_RIDE_PUSH) {
                RideLogPush rideLogPush = JSONObject.parseObject(object.getString("data"), RideLogPush.class);

                log.info("订单推送：{}，mainValid：{}",rideLogPush.getOrderNO(), rideLogPush.getMainValid());

                String newTime = DateTimeUtil.getNowTime();

                handleUserInfo(rideLogPush);

                if (dataService.getAddFee(rideLogPush.getAccountId()) != null) {
                    /**判断车辆是否在站内*/
                    Machine machine = machineService.getByUseCode(rideLogPush.getUserCode());
                    /**借车推送*/
                    String key = RedisConstant.REDIS_CLIENT_RIDELOG_PUSH + rideLogPush.getUserCode();
                    if (rideLogPush.getType().equals(RideLogPushConstant.TYPE_BORROW)) {
                        Integer time = dataService.getAddFee(rideLogPush.getAccountId()).getFreeTime() * 60;
                        redisService.add(key, rideLogPush.getReturn_time(), time <= 0 ? 1 : time);

                        //redisService.add(RedisConstant.REDIS_CLIENT_RIDELOG_PUSH_HTML+);
                    }
                    /**还车推送*/
                    else {
                        boolean mainValid = Optional.ofNullable(rideLogPush.getMainValid()).orElse(true);

                        /**删除管理平台车辆低电缓存*/
                        redisService.del(RedisConstant.MACHINE_BORROW_SOC_MANAGER + rideLogPush.getMachineNO());
                        /**删除运维车辆低电缓存*/
                        redisService.del(RedisConstant.MACHINE_BORROW_SOC_MAIN + rideLogPush.getMachineNO());


                        /*有盈利删除无盈利订单*/
                        if (Objects.isNull(redisService.get(key))){
                            machineNoIncomeService.del(rideLogPush.getUserCode(), rideLogPush.getAccountId());
                        }

                        /**判断是否为无收益车辆*/
                        if (redisService.get(key) != null) {
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            MachineNoIncome machineNoIncome = new MachineNoIncome();
                            machineNoIncome.setAccountId(rideLogPush.getAccountId());
                            machineNoIncome.setOrderNO(rideLogPush.getOrderNO());
                            machineNoIncome.setUserCode(rideLogPush.getUserCode());
                            machineNoIncome.setMachineId(machine.getMachineId());
                            machineNoIncome.setAddTime(newTime);
                            machineNoIncome.setTime(Math.abs(sdf.parse(redisService.get(key)).getTime() - sdf.parse(rideLogPush.getReturn_time()).getTime()) / 1000);
                            machineNoIncomeService.insert(machineNoIncome);

                        } else if (mainValid) {
                            List<MachineNoIncome> machineNoIncomes = machineNoIncomeService.getByUserCode(rideLogPush.getUserCode(), rideLogPush.getAccountId());
                            if (CollUtil.isNotEmpty(machineNoIncomes)) {
                                machineNoIncomeService.del(rideLogPush.getUserCode(), rideLogPush.getAccountId());
                            }

                            /**获取换电工单id*/
                            String redisPower = redisService.get(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + rideLogPush.getMachineNO());
                            if (redisPower != null) {
                                List<PowerChangeRedis> powerChangeRedisList = new LinkedList<>();
                                try {
                                    powerChangeRedisList = JSON.parseArray(redisPower, PowerChangeRedis.class);
                                } catch (JSONException error) {
                                    log.error(error.getMessage(), error);
                                    redisService.del(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + rideLogPush.getMachineNO());
                                }

                                if (CollUtil.isNotEmpty(powerChangeRedisList)) {
                                    /**循环遍历多个审核中记录*/
                                    Iterator<PowerChangeRedis> it = powerChangeRedisList.iterator();
                                    while (it.hasNext()) {
                                        PowerChangeRedis powerChangeRedis = it.next();
                                        String remark = null;
                                        Integer isValid = null;
                                        if (DateTimeUtil.getTime(powerChangeRedis.getTime(), newTime) <= powerChangeRedis.getRideTime() * 3600) {
                                            LogUtil.info("换电还车有效：" + rideLogPush.getMachineNO());
                                            isValid = 1;
                                            remark = WorkOrderConstant.sys_rideTime_isValid;
                                        } else {
                                            LogUtil.info("换电还车无效：" + rideLogPush.getMachineNO());
                                            isValid = 0;
                                            remark = WorkOrderConstant.sys_rideTime_Valid;
                                        }
                                        /**修改换电工单*/
                                        WorkOrder workOrderDB = workOrderService.getByWorkOrderId(powerChangeRedis.getWorkOrderId());
                                        if (workOrderDB != null) {
                                            WorkOrder workOrder = new WorkOrder();
                                            workOrder.setWorkOrderId(powerChangeRedis.getWorkOrderId());
                                            workOrder.setState(WorkOrderConstant.state_WC);
                                            workOrder.setIsValid(isValid);
                                            workOrder.setRemark(workOrderDB.getRemark() + remark);
                                            workOrderService.update(workOrder);
                                        }
                                        /**修改换电记录*/
                                        PowerChangeLog powerChangeLog = powerChangeLogService.getPowerChangeLogId(powerChangeRedis.getPowerChangeId());
                                        powerChangeLogService.update(powerChangeRedis.getPowerChangeId(), null, isValid, powerChangeLog.getRemark() + remark, newTime);
                                        /**审核后删除*/
                                        it.remove();

                                        // 运维绩效-修改有效性逻辑
                                        powerChangeLog.setIsValid(isValid);
                                        powerChangePerformanceService.calculateAndInsertPerformance(powerChangeLog);
                                    }
                                }

                                /**判断是否为空，删除缓存*/
                                if (CollUtil.isNotEmpty(powerChangeRedisList)) {
                                    /**获取配置*/
                                    AccountConfig accountConfig = dataService.getAccountConfig(rideLogPush.getAccountId());
                                    redisService.add(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + rideLogPush.getMachineNO(), JSONObject.toJSONString(powerChangeRedisList), 3600 * accountConfig.getRideTime() + 1200);
                                } else {
                                    redisService.del(RedisConstant.REDIS_TER_BATTERY_CHANGE_RIDE + rideLogPush.getMachineNO());
                                    /**二级缓存*/
                                    redisService.del(RedisConstant.REDIS_TER_BIKE_BATTERY_CHANGE_RIDE_MAP, rideLogPush.getMachineNO());
                                }
                            }

                            /**获取调度记录id*/
                            String redisDispatch = null;
                            try {
                                redisDispatch = redisService.get(RedisConstant.REDIS_TER_DISPATCH_CHANGE_RIDE + rideLogPush.getMachineNO());
                            } catch (SerializationException e) {
                                redisService.del(RedisConstant.REDIS_TER_DISPATCH_CHANGE_RIDE + rideLogPush.getMachineNO());
                            }

                            if (redisDispatch != null) {
                                LogUtil.info("订单推送，调度：" + redisDispatch);
                                List<PowerChangeRedis> powerChangeRedisList = new LinkedList<>();
                                try {
                                    powerChangeRedisList = JSON.parseArray(redisDispatch, PowerChangeRedis.class);
                                } catch (JSONException e) {
                                    redisService.del(RedisConstant.REDIS_TER_DISPATCH_CHANGE_RIDE + rideLogPush.getMachineNO());
                                }

                                if (CollUtil.isNotEmpty(powerChangeRedisList)) {
                                    /**循环遍历多个审核中记录*/
                                    Iterator<PowerChangeRedis> it = powerChangeRedisList.iterator();
                                    while (it.hasNext()) {
                                        PowerChangeRedis powerChangeRedis = it.next();
                                        String remark;
                                        int isValid;
                                        if (DateTimeUtil.getTime(powerChangeRedis.getTime(), newTime) <= powerChangeRedis.getRideTime() * 3600) {
                                            //LogUtil.info("调度还车有效："+rideLogPush.getMachineNO());
                                            isValid = 1;
                                            remark = WorkOrderConstant.sys_rideTime_isValid;
                                            //LogUtil.info("订单推送调度：有效");
                                        } else {
                                            LogUtil.info("调度还车无效：" + rideLogPush.getMachineNO());
                                            isValid = 0;
                                            remark = WorkOrderConstant.sys_rideTime_Valid;
                                            //LogUtil.info("订单推送调度：有效");
                                        }
                                        DispatchLog dispatchLog = dispatchLogService.getById(powerChangeRedis.getPowerChangeId());
                                        remark = dispatchLog.getRemark() + remark;

                                        /**修改调度工单*/
                                        WorkOrder workOrderDB = workOrderService.getByWorkOrderId(powerChangeRedis.getWorkOrderId());
                                        if (workOrderDB != null) {
                                            WorkOrder workOrder = new WorkOrder();
                                            workOrder.setWorkOrderId(powerChangeRedis.getWorkOrderId());
                                            workOrder.setState(WorkOrderConstant.state_WC);
                                            workOrder.setIsValid(isValid);
                                            workOrder.setRemark(remark);
                                            workOrderService.update(workOrder);
                                        }

                                        dispatchLogService.audit(powerChangeRedis.getPowerChangeId(), isValid, remark, newTime);
                                        /**审核后删除*/
                                        it.remove();

                                        // 运维绩效-修改有效性逻辑
                                        dispatchLog.setIsValid(isValid);
                                        dispatchPerformanceService.calculateAndInsertPerformance(dispatchLog);
                                    }
                                }

                                /**判断是否为空，删除缓存*/
                                if (CollUtil.isNotEmpty(powerChangeRedisList)) {
                                    /**获取配置*/
                                    AccountConfig accountConfig = dataService.getAccountConfig(rideLogPush.getAccountId());
                                    redisService.add(RedisConstant.REDIS_TER_DISPATCH_CHANGE_RIDE + rideLogPush.getMachineNO(), JSONObject.toJSONString(powerChangeRedisList), 3600 * accountConfig.getRideTime() + 1200);
                                    //LogUtil.info("订单推送，调度添加："+rideLogPush.getMachineNO()+";"+powerChangeRedisList.toString()+";"+(3600*accountConfig.getRideTime()+1200));
                                } else {
                                    redisService.del(RedisConstant.REDIS_TER_DISPATCH_CHANGE_RIDE + rideLogPush.getMachineNO());
                                    //LogUtil.info("订单推送，调度删除："+rideLogPush.getMachineNO());
                                    /**二级缓存*/
                                    redisService.del(RedisConstant.REDIS_TER_BIKE_DISPATCH_CHANGE_RIDE_MAP, rideLogPush.getMachineNO());
                                    //LogUtil.info("订单推送，调度二级删除："+rideLogPush.getMachineNO());
                                }
                            }

                            String ordersAfterLastDispatchMachineKey = String.format(RedisConstant.ORDERS_AFTER_LAST_DISPATCH_MACHINE, machine.getMachineId());
                            String ordersAfterLastDispatchMachineCache = redisService.get(ordersAfterLastDispatchMachineKey);
                            if (StrUtil.isNotBlank(ordersAfterLastDispatchMachineCache)) {
                                // 更新首次产生订单时间和有效订单数
                                dispatchLogService.updateFistOrderTimeAndAfterValidOrder(machine.getMachineId());
                            }
                            /**挪车记录和工单状态判断*/
                            this.updateMoveLogAndWorkOrder(rideLogPush,newTime);

                            // 运维绩效-新订单触发更新绩效(订单时段/时效规则)
                            dispatchPerformanceService.updatePerformanceByNewOrder(machine.getMachineId(), rideLogPush.getOrderNO());
                            powerChangePerformanceService.updatePerformanceByNewOrder(machine.getMachineId(), rideLogPush.getOrderNO());
                            movePerformanceService.updatePerformanceByNewOrder(machine.getMachineId(), rideLogPush.getOrderNO());
                        }

                        if (rideLogPush.getOrderType().equals(RideLogPushConstant.ORDER_TYPE_DISPATCH)) {
                            // 获取车辆的围栏配置
                            List<Point> points = dataService.getGeo(machine.getAccountId());
                            // 还车位置
                            Point point = new Point(rideLogPush.getLon(), rideLogPush.getLat());
                            // 是否在围栏内
                            boolean isInArea = GeoUtil.IsPtInPoly(point, points);

                            // true:站外, false:超区
                            Integer locationType = isInArea ? MachineLocationTypeConstant.OUT_SITE_MOVE : MachineLocationTypeConstant.SUPER_ZONE_MOVE;

                            workOrderQuartzService.WorkOrder_NC(machine, locationType);
                        } else if (rideLogPush.getOrderType().equals(RideLogPushConstant.ORDER_TYPE_NORMAL)) {
                            WorkOrderFinishing workOrderFinishing = workOrderFinishingService.getByMachineIdWorkType(machine.getMachineId(), WorkOrderConstant.workType_NC, rideLogPush.getAccountId());
                            if (workOrderFinishing != null) {
                                LogUtil.info("挪车调度无效工单：" + workOrderFinishing);
                                workOrderQuartzService.delWorkOrder(workOrderFinishing.getWorkOrderId(), workOrderFinishing);
                                workOrderQuartzService.JPush(workOrderFinishing.getGetUserId(), WorkOrderConstant.buildType_V, workOrderFinishing.getWorkType(), WorkOrderConstant.update_Work);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private void handleUserInfo(RideLogPush rideLogPush) {
        try {
            log.info("处理用户信息,rideLogPush:{}", rideLogPush);
            if (RideLogPushConstant.ORDER_TYPE_NORMAL.equals(rideLogPush.getOrderType())
                    || RideLogPushConstant.ORDER_TYPE_DISPATCH.equals(rideLogPush.getOrderType())) {
                // 还车 更新用户信息-最后骑车时间 设备信息-最后骑行时间
                userInfoService.updateLastRideTime(rideLogPush);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }


    private void updateMoveLogAndWorkOrder(RideLogPush rideLogPush,String nowTime){
        String redisMove = null;
        try {
            redisMove = redisService.get(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + rideLogPush.getMachineNO());
        } catch (SerializationException e) {
            redisService.del(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + rideLogPush.getMachineNO());
        }

        if (redisMove != null) {
            log.info("订单推送，挪车：" + redisMove);
            List<PowerChangeRedis> powerChangeRedisList = new LinkedList<>();
            try {
                powerChangeRedisList = JSON.parseArray(redisMove, PowerChangeRedis.class);
            } catch (JSONException e) {
                redisService.del(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + rideLogPush.getMachineNO());
            }

            if (CollUtil.isNotEmpty(powerChangeRedisList)) {
                /**循环遍历多个审核中记录*/
                Iterator<PowerChangeRedis> it = powerChangeRedisList.iterator();
                while (it.hasNext()) {
                    PowerChangeRedis powerChangeRedis = it.next();
                    MoveLog moveLog = moveLogService.getById(powerChangeRedis.getPowerChangeId());
                    StringBuilder remark = new StringBuilder(moveLog.getRemark()).append("；").append(powerChangeRedis.getRideTime()).append("小时");
                    int isValid;
                    if (DateTimeUtil.getTime(powerChangeRedis.getTime(), nowTime) <= powerChangeRedis.getRideTime() * 3600) {
                        //LogUtil.info("调度还车有效："+rideLogPush.getMachineNO());
                        isValid = 1;
                        remark.append(WorkOrderConstant.sys_rideTime_isValid_move);
                        //LogUtil.info("订单推送调度：有效");
                    } else {
                        log.info("挪车还车无效：" + rideLogPush.getMachineNO());
                        isValid = 0;
                        remark.append(WorkOrderConstant.sys_rideTime_Valid);
                        //LogUtil.info("订单推送调度：有效");
                    }

                    /**修改调度工单*/
                    WorkOrder workOrderDB = workOrderService.getByWorkOrderId(powerChangeRedis.getWorkOrderId());
                    if (workOrderDB != null) {
                        WorkOrder workOrder = new WorkOrder();
                        workOrder.setWorkOrderId(powerChangeRedis.getWorkOrderId());
                        workOrder.setState(WorkOrderConstant.state_WC);
                        workOrder.setIsValid(isValid);
                        workOrder.setRemark(remark.toString());
                        workOrderService.update(workOrder);
                    }

                    moveLogService.audit(powerChangeRedis.getPowerChangeId(),Objects.equals(WorkOrderConstant.valid,isValid), remark.toString());
                    /**审核后删除*/
                    it.remove();

                    // 运维绩效-修改有效性逻辑
                    moveLog.setIsValid(Objects.equals(WorkOrderConstant.valid,isValid));
                    movePerformanceService.calculateAndInsertPerformance(moveLog);
                }
            }

            /**判断是否为空，删除缓存*/
            if (CollUtil.isNotEmpty(powerChangeRedisList)) {
                /**获取配置*/
                AccountConfig accountConfig = dataService.getAccountConfig(rideLogPush.getAccountId());
                //找到最大的时间
                Integer rideTime = powerChangeRedisList.stream().max(Comparator.comparing(PowerChangeRedis::getTime)).map(PowerChangeRedis::getRideTime).orElse(accountConfig.getRideTime());
                redisService.add(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + rideLogPush.getMachineNO(), JSONObject.toJSONString(powerChangeRedisList), (3600 * rideTime) + 3600);
                log.info("订单推送，挪车添加："+rideLogPush.getMachineNO()+";"+JSON.toJSONString(powerChangeRedisList)+";"+(3600*rideTime+3600));
            } else {
                redisService.del(RedisConstant.REDIS_TER_MOVE_CHANGE_RIDE + rideLogPush.getMachineNO());
                //LogUtil.info("订单推送，调度删除："+rideLogPush.getMachineNO());
                /**二级缓存*/
                redisService.del(RedisConstant.REDIS_TER_BIKE_MOVE_CHANGE_RIDE_MAP, rideLogPush.getMachineNO());
                //LogUtil.info("订单推送，调度二级删除："+rideLogPush.getMachineNO());
            }
        }
    }


}
